#include <USBKeyboard.h>

#define output_pins_len 8                                                      //OUTPUT针脚数
char last_keycode[output_pins_len] = {255, 255, 255, 255, 255, 255, 255, 255}; //定义了多少个OUTPUT针脚需要在大括号里填入多少个255
#define base_key 24                                                            //MIDI键盘第一个键的音高
//USB需要飞线，飞线图请见我仓库内的图片
//INPUT的针脚必须是PD3,PD4,PD5,PD6,PD7,PB0,PB1,PB2（有顺序之分）
//在"Arduino UNO"或"ATTINY88 MH-ET"上的引脚为3，4，5，6，7，8，9，10
const uint8_t output_pins[] = {25, 24, 23, 22, 21, 20, 19, 18}; //OUTPUT针脚可以随意定，定义了几个针脚需要把output_pins_len后面的数改为针脚数。
const uint8_t input_pins[]={3,4,5,6,7,8,9,10};//不能修改，因为用了寄存器写代码
int repeat_count = 0;

USBKeyboard midi = USBKeyboard();
char pincode;
int new_keystatue;
int last_keystatue;

void check_keys(char last_keycode[])
{
    for (int i = 0; i < output_pins_len; i++)
    {
        fastdigitalWrite(output_pins[i], LOW);
        pincode = ((PIND & B11111000) >> 3) | ((PINB & B00000111) << 5);
        fastdigitalWrite(output_pins[i], HIGH);

        for (int b = 0; b < 8; b++)
        {
            new_keystatue = (pincode >> b) & 1;
            last_keystatue = (last_keycode[i] >> b) & 1;
            if (last_keystatue < new_keystatue)
            {
                midi.sendmidi(b * 8 + i + base_key, 0x80 + 0, 127);
            }
            else if (last_keystatue > new_keystatue)
            {
                midi.sendmidi(b * 8 + i + base_key, 0x90 + 0, 127);
            }
        }
        last_keycode[i] = pincode;
    }
}

void setup()
{
    /*DDRD = 0;
    PORTD = B11111000;
    DDRB = 0;
    PORTB = B00000111;*/
    for (int i = 0 ; i<8;i++ ){
      pinMode(input_pins[i],INPUT_PULLUP);
    }

    for (int i = 0; i < output_pins_len; i++)
    {
        pinMode(output_pins[i], OUTPUT);
        digitalWrite(output_pins[i], HIGH);
    }
}

void fastdigitalWrite(uint8_t pin, uint8_t val) //简化了正常的digitalWrite的步骤，节省时间。
{
    uint8_t bit = digitalPinToBitMask(pin);
    uint8_t port = digitalPinToPort(pin);
    volatile uint8_t *out;
    out = portOutputRegister(port);

    uint8_t oldSREG = SREG;
    cli();

    if (val == LOW)
    {
        *out &= ~bit;
    }
    else
    {
        *out |= bit;
    }

    SREG = oldSREG;
}

void loop()
{
    check_keys(last_keycode);
    if (repeat_count == 30) //没必要每次都执行USBPULL
    {
        midi.update();
        repeat_count = 0;
    }
    repeat_count += 1;
}
